#ifdef USE_LWIP

#include <logger_rte.h>
#include <plc_rte.h>
#include <IPAddress.h>
#include "ETH_LWIP.h"
#include "Holder.h"

#ifdef USE_EMAIL

#include <Email.h>

#endif
#ifdef USE_HTTPD

#include <WebServer.h>

#endif

extern "C"
{
void iperf_server_socket_init();

void iperf_server_netconn_init();

void iperf_client_socket_init();

void iperf_client_netconn_init();
}

int ETH_LWIP::begin(uint32_t tick) {
    union {
        uint32_t ui;
        uint8_t uc[4];
    } u;
#if LWIP_DHCP
    if (rte_config.lwip.dhcp) {
        Ethernet.begin();
        logger.debug("GET DHCP IP: %d.%d.%d.%d\n", Ethernet.localIP()[0], Ethernet.localIP()[1], Ethernet.localIP()[2],
                     Ethernet.localIP()[3]);
        rte_config.lwip.ip = Ethernet.localIP();
    } else
#endif
    {
        IPAddress ipp(rte_config.lwip.ip);
        IPAddress subnet(rte_config.lwip.mask);
        IPAddress gateway(rte_config.lwip.gw);
#if LWIP_DNS
        IPAddress dnsServer(rte_config.lwip.dns);
#endif
        Ethernet.begin(ipp, subnet, gateway
#if LWIP_DNS
                , dnsServer
#endif
        );
//        logger.debug("net begined.\n");
    }
    logger.debug("IP: %d.%d.%d.%d\n", Ethernet.localIP()[0], Ethernet.localIP()[1], Ethernet.localIP()[2],
                 Ethernet.localIP()[3]);
    logger.debug("MAC=%x:%x:%x:%x:%x:%x", gnetif.hwaddr[0], gnetif.hwaddr[1], gnetif.hwaddr[2], gnetif.hwaddr[3],
                 gnetif.hwaddr[4], gnetif.hwaddr[5]);
    logger.debug("gateway=%d.%d.%d.%d", ip4_addr_get_byte(&gnetif.gw, 0), ip4_addr_get_byte(&gnetif.gw, 1),
                 ip4_addr_get_byte(&gnetif.gw, 2), ip4_addr_get_byte(&gnetif.gw, 3));
    logger.debug("netmask=%d.%d.%d.%d", ip4_addr_get_byte(&gnetif.netmask, 0), ip4_addr_get_byte(&gnetif.netmask, 1),
                 ip4_addr_get_byte(&gnetif.netmask, 2), ip4_addr_get_byte(&gnetif.netmask, 3));
#if LWIP_DNS
    u.ui = rte_config.lwip.dns;
    logger.debug("dnsServer=%d.%d.%d.%d", u.uc[3], u.uc[2], u.uc[1], u.uc[0]);
#endif
#ifdef USE_IPERF_SERVER
    iperf_server_socket_init();
    iperf_server_netconn_init();
#endif
#if defined(USE_IPERF_CLIENT)
    iperf_client_socket_init();
    iperf_client_netconn_init();
#endif
#ifdef USE_EMAIL_TEST
    Email mail;
    mail.test();
#endif
    return 0;
}

extern "C" void phy_dump();

int ETH_LWIP::diag(uint32_t tick) {
    // HAL_ETH_RxCpltCallback(0);
    // phy_dump();
    return Ethernet.diag(tick);
}

int ETH_LWIP::run(uint32_t tick) {
    static uint32_t last;
    union {
        uint32_t ui;
        uint8_t uc[4];
    } u;
    if (tick > last) {
        if (diag(tick) < 0) {
            // end();
            // netif_set_link_down(&gnetif);
        } else {
            // ethernetif_init(&gnetif);
            // netif_set_link_up(&gnetif);
        }
        last = tick + 10000;
    }
    if (eth1.data.ipSet) {
        IPAddress ipp(rte_config.lwip.ip);
        Ethernet.set_ip(ipp);
        u.ui = rte_config.lwip.ip;
        logger.info("set ip = %d.%d.%d.%d", u.uc[0], u.uc[1], u.uc[2], u.uc[3]);
        eth1.data.ipSet = 0;
    }
#if LWIP_DHCP
    data.dhcp=rte_config.lwip.dhcp;
#endif
    data.ip = Ethernet.localIP();
    data.mask = Ethernet.subnetMask();
    data.gw = Ethernet.gatewayIP();
    data.dns = Ethernet.dnsServerIP();
    for (int i = 0; i < 6; i++) {
        mac.bytes[i] = gnetif.hwaddr[i];
    }
    mac.size = 6;
    data.mac = (pb_bytes_array_t *) (&mac);
    data.state = is_connected();
    return 0;
}

void ETH_LWIP::set_ip() {
    eth1.data.ipSet = 1;
}

void ETH_LWIP::end() {
    Ethernet.end();
}

#ifdef __PLATFORMIO_BUILD_DEBUG__
int ETH_LWIP::dev_test(uint32_t tick) {
    return 0;
}
#endif

ETH_LWIP::ETH_LWIP() {
    rte_config.lwip.ip = (DEFAULT_IP4 << 24) | (DEFAULT_IP3 << 16) | (DEFAULT_IP2 << 8) | DEFAULT_IP1;
    rte_config.lwip.mask = 0xffffff;
    rte_config.lwip.gw = (DEFAULT_IP3 << 16) | (DEFAULT_IP2 << 8) | DEFAULT_IP1 | 1 << 24;
#if LWIP_DNS
    rte_config.lwip.dns = (1 << 24) | (DEFAULT_IP3 << 16) | (DEFAULT_IP2 << 8) | DEFAULT_IP1;
#endif
}

bool ETH_LWIP::is_connected() {
    return gnetif.flags & NETIF_FLAG_LINK_UP;
}

#endif


